スタジオが成長するにつれて、手作業のパイプラインに生じたほころびがより大きく目立つようになります。アーティストがアセットをパブリッシュし、スーパーバイザーがショットを承認し、タスクがDoneに切り替わる。しかし、どこかの段階で別のツールがまだ「何かを言われ待ち」になっている。そうした遅れは積み重なっていきます。
KitsuのEvent APIは、制作で何が起きたかを、その瞬間に配信することで状況を一変させます。ポーリングも、推測も不要です。行動に移せるリアルタイムのシグナルだけが得られます。
webhookを使えば、レンダリングの起動、トラッキングツールの同期、チームへの通知、あるいは人を介した引き継ぎなしでの下流システムの更新などのように、制作データが変化した瞬間に自動アクションをトリガーできます。
この記事では、セットアップ方法と、それを実際に活用する手順を解説します。スタジオで検証済みの実用的な例を、リアルなパイプラインにそのまま組み込めます。
このガイドで紹介しているサンプル統合の完全なソースコードは、GitHubで確認できます:
🔗 https://github.com/cgwire/blog-tutorials/tree/main/kitsu-webhooks%20
なぜwebhookなのか

数分おきにAPIをポーリングするのは、フロア中に叫んで「更新はないのか」と制作に尋ねるようなものです。遅い上に騒がしく、しかも「問題が起きた瞬間」を見逃しやすい。
webhookはこのモデルを反転させます。Kitsuが変わったかどうかを確認するのではなく、Kitsuが変化した瞬間にあなたのパイプラインへすぐに伝えてくれるのです。
これにより、実際の制作では複数のメリットがあります。たとえばモデラーがKitsuで新しいプロップを作成すると、数秒以内に、アセット構築システムがサーバー上で正しいディレクトリ構造を立ち上げます。さらにDCCツールにアセットを登録し、レイアウトから見えるようにします。誰も名前をコピーしたり、ボタンをクリックしたりする必要はありません。
後のスケジュールで、ライティングのタスクがDoneに移動するとします。たった1回のステータス変更が、レンダーマネジメントシステムに対してショットを自動提出させるトリガーになります。最新の承認済みファイルと、そのショーに適した正しいレンダー設定を使います。誰かがタスクの完了に気づく頃には、すでにフレームがレンダリングされている状態です。
アーティストがファイルをパブリッシュしたとき、webhookはそのバージョンをそのままレビュー用スタックへ押し込むこともできます。承認済みが開封される前にメディアをトランスコードし、アップロードし、正しいショットに紐づけます。レビューはより早く行われ、ノートはより速く返り、作業は「誰かが次の手順を思い出すのを待つ」状態から解放されて流れ続けます。
つまりwebhookがもたらすのはこれです。制作データが、そのままアクションに直結すること。引き継ぎが減り、フィードバックループがより密になり、アーティストが作業するのと同じスピードでパイプラインが反応できるようになります。
利用可能なイベント
Kitsuは、利用可能なデータモデルでカバーされている制作アクションすべてに対してイベントを発行します:
- アセットの作成と更新
- ショットの作成と更新
- タスクステータスの変更
- プレビュー用ファイルの作成とパブリッシュ
- 人(担当)の管理
- 組織の変更
- ショットおよびシーケンスの更新
各イベントには構造化されたデータ(ID、タイムスタンプ、ユーザー情報など)が含まれるため、何が変わったのかを正確に特定し、それに応じてリアクションできます。購読できるリアルタイムの制作ログです!
1. イベントリスナーを作成する
最初のステップは、Kitsu Pythonクライアント(gazu)を使ってイベントリスナーを登録することです。このリスナーはwebhookエンドポイントのように振る舞います。つまり、イベントを待ち、発生したらコールバック関数を呼び出します。
import gazugazu.set_host("http://localhost/api") gazu.set_event_host("http://localhost/api") user = gazu.log_in("admin@example.com", "mysecretpassword")
def my_callback(data): print("Asset created %s" % data"asset_id")
event_client = gazu.events.init() gazu.events.add_listener(event_client, "asset:new", my_callback) gazu.events.run_client(event_client)
まず、Kitsu向けの公式PythonクライアントであるGazuをインポートし、ローカルで動作するKitsuサーバーに接続するように設定します。set_hostとset_event_hostは、どちらも同じAPI URLを指しています。前者は通常のREST呼び出しに使われ、後者はイベント(websocket)エンドポイントに特化しています。本番では、イベントを聴く処理がブロッキングになるため、2つを別スレッドで設定することが推奨されます。ただしこのチュートリアルでは、わかりやすさのために1つのエンドポイントでまとめて行います。
次に、ユーザーとして認証します。gazu.log_inを呼び出すと、指定した資格情報でログインされ、セッションが確立されるため、クライアントがKitsuからのイベントを受け取る権限を得ます。
my_callback関数は、イベントを受け取ったときにパイプラインがどう反応するかを定義します。入力としてイベントのペイロードを受け取り、この場合は新しく作成されたアセットのIDを単に表示するだけです。中規模のアニメーションスタジオでは、このコールバックが、たとえばKitsuに新しいアセットが追加されたときにファイルサーバーへ標準化されたディレクトリ構造を作成するスクリプトをトリガーする、という形になるかもしれません。アーティストは手作業で設定する必要がなくなり、命名規則も一貫性を保てます。
その後、gazu.events.init()でイベントクライアントを初期化します。このクライアントは、Kitsuのイベントシステムへの永続的な接続を維持します。
gazu.events.add_listenerの呼び出しは、特定のイベントタイプに対してコールバック関数を登録します:"asset:new"。これはGazuに対して、「Kitsuが新しいアセットが作成されたことを示すイベントを発行したら、イベントデータを使ってmy_callbackを呼び出してほしい」と伝えるものです。
最後に、gazu.events.run_client(event_client)がイベントループを開始します。この時点以降、スクリプトはブロックされ、WebSocket接続を通じて継続的に待ち受けます。Kitsuで誰かがアセットを作成するとすぐに、Kitsuがasset:newイベントを発行し、Gazuが受け取り、my_callbackが即座に実行されます。
2. テストイベントを送信する
セットアップを検証するには、実際のイベントを生成する必要があります。最も簡単な方法は、すでに本番で使っている標準APIアクションを実行することです。たとえば、アセットをプログラムで作成してみます:
import gazugazu.set_host("http://localhost/api") user = gazu.log_in("admin@example.com", "mysecretpassword")
projects = gazu.project.all_projects() project = projects0
asset_types = gazu.asset.all_asset_types() asset_type = asset_types0
asset = gazu.asset.new_asset( project, asset_type, "My new asset", "My asset description" )
認証の後、gazu.project.all_projects()を呼び出してログイン済みユーザーから見えるすべてのプロジェクトの一覧を取得します。そのリストから最初のプロジェクトを選択します。本番の制作ツールでは通常、名前やIDで特定のプロジェクトを探すことが多いですが、この例ではシンプルに保ちます。
アセットタイプでも同様のパターンを使います。スクリプトは利用可能なすべてのアセットタイプを問い合わせ、最初のものを選びます。アセットタイプは、どのような種類のアセットを作成するか(キャラクター、プロップ、環境など)を定義し、新しいアセットを作成する際にKitsuでは指定が必須です。
プロジェクトとアセットタイプを用意したら、gazu.asset.new_assetを呼び出して新しいアセットを作成します。この関数は、対象プロジェクト、アセットタイプ、名前、説明を受け取ります。この呼び出しが成功すると、Kitsuは即座に自分のデータベースへアセットを作成し、作成されたばかりのアセットオブジェクトを返します。
この時点でアセットは、Webインターフェースから作成されたかのようにKitsuに存在します。このアクションはまた、残りのパイプラインが自動的に反応できるように、asset:newイベントを発行します。
スタジオ全体に展開する前に、パイプラインTDがステージング用のプロジェクトでアセットを作成し、実運用データに触れることなく、イベントが下流のオートメーションを確かにトリガーするかを確認することができます。
3. コールバックでイベントにリアクションする
コールバックは、Kitsuのイベントが具体的なパイプラインアクションへ変わるポイントです。コールバックが実行されると、何が変わったのかを正確に説明するペイロードが渡されます。たとえばアセットが作成された、タスクが新しいステータスへ移動した、ファイルがパブリッシュされた、などです。このペイロードが、オートメーションを動かすための入口になります。
コールバック内で最初に行われることが多いのは、イベントデータに含まれるIDを使ってKitsuから完全なコンテキストを引き出すことです。たとえばタスク更新イベントを受け取った場合、変更が制作のどこで起きたのか、どのルールが適用されるべきかを理解するために、完全なタスク、紐づいたショット、関連するプロジェクトを取得できます。
そこから先は、多くの場合、コールバックが本来手動の介入を要するであろう副作用(サイドエフェクト)を実行します。アセット作成イベントは、たとえばディスク上に標準化されたフォルダーのツリーを作成することにつながるかもしれません。ファイルのパブリッシュイベントは、メディアをレビューシステムへ投入し、メタデータを紐づけ、スーパーバイザーにすぐ見えるようにします。
重要な考え方は、コールバックによって制作の状態が振る舞いを決めることです。人が更新に反応するのではなく、あなたのパイプラインが、毎回同じルールで一貫して、かつ即時に反応します。
こちらの例のGithubリポジトリをフォークして、自分で試してみてください。
4. イベントを検索する
ライブイベントは全体の半分にすぎません。Kitsuは過去のイベントも記録しており、実際に制作で何が起きたのかを信頼できる形で追跡できます。何かがうまくいかなかったとき、または「うまく動いた」ことを証明する必要があるとき、このイベント履歴は欠かせないデバッグ手段です。
APIを通じて、最近のイベントを照会したり、期間やイベントタイプでフィルタリングしたりできます。直近の100件を引っ張るだけで、失敗直後の状況把握に十分なことが多いです。照会を特定の日時範囲に絞れば、そのシフトや夜間バッチの間に何が起きたかを詳しく調べられます。ファイル関連のイベントに絞り込むのは、パブリッシュやメディア取り込みの問題を追跡する際に特に有用です。
events = gazu.client.get("data/events/last?page_size=100")
events = gazu.client.get("data/events/last?page_size=100&before=2019-02-01")
events = gazu.client.get("data/events/last?page_size=100&before=2019-02-01&after=2019-01-01")
events = gazu.client.get("data/events/last?page_size=100&only_files=true")
実際には、これを使うことで壊れたオートメーションを復元できます。たとえば、夜のどこかでパブリッシュスクリプトが失敗し、朝のチームがレビューシステム上でメディアが欠けているのを見つけたとします。アーティストに「いつパブリッシュしたのか」を聞いたり、複数のマシンにまたがるログを掘り起こしたりする代わりに、前日分のすべてのファイルイベントをKitsuに問い合わせられます。そうすれば、パブリッシュの正確な時系列、タイムスタンプ、ユーザー、紐づいたエンティティを把握できます。
また、生産性レポートのために、パイプライン内で特定のイベントを追跡することもできます。たとえば、アニメーションチームの活動ログをまとめて「誰が何をしたか」を知る、というようなことです。
まとめ
Kitsu APIのイベントは、リアクティブなパイプラインを構築するための、きれいで信頼できる手段を提供します。ポーリングして変化を探すのではなく制作の変化を待ち受けることで、遅延を減らし、手作業のステップを排除し、スタジオがスケールしていく際にもより強靭になります。
もちろん、webhookはKitsuのスクリプトに対するあなたの知識の範囲でしか進められません。より技術的なチュートリアルについては、ぜひブログもチェックして、どんなものを作れるかのイメージをつかんでください!


